export const isObject = (value) => {
  return value !== null && typeof value === "object";
};

export const isFunction = (value) => {
  return typeof value === "function";
};

export function isString(value) {
  return typeof value === "string";
}

export function isNumber(value) {
  return typeof value === "number";
}

export function invokeArrayFn(fns) {
  fns && fns.forEach((fn) => fn());
}

export function ensureArray(val) {
  return Array.isArray(val) ? val : [val];
}

// 用位运算 针对特定值可以组合
// 00000010 2
// 00000100 4

// 00000110 6 &
// 00000010 2
// 00000010 > 0   （6中包含2 说明函数式组件是组件）

export let ShapeFlags;
(function (ShapeFlags) {
  ShapeFlags[(ShapeFlags["ELEMENT"] = 1)] = "ELEMENT"; // 元素
  ShapeFlags[(ShapeFlags["FUNCTIONAL_COMPONENT"] = 1 << 1)] =
    "FUNCTIONAL_COMPONENT"; // 函数式组件
  ShapeFlags[(ShapeFlags["STATEFUL_COMPONENT"] = 1 << 2)] =
    "STATEFUL_COMPONENT"; // 状态组件
  ShapeFlags[(ShapeFlags["TEXT_CHILDREN"] = 1 << 3)] = "TEXT_CHILDREN"; // 文本
  ShapeFlags[(ShapeFlags["ARRAY_CHILDREN"] = 1 << 4)] = "ARRAY_CHILDREN"; // 数组孩子
  ShapeFlags[(ShapeFlags["SLOTS_CHILDREN"] = 1 << 5)] = "SLOTS_CHILDREN"; // 插槽
  ShapeFlags[(ShapeFlags["TELEPORT"] = 1 << 6)] = "TELEPORT"; // 传送门
  ShapeFlags[(ShapeFlags["SUSPENSE"] = 1 << 7)] = "SUSPENSE"; // suspense 组件
  ShapeFlags[(ShapeFlags["COMPONENT_SHOULD_KEEP_ALIVE"] = 1 << 8)] =
    "COMPONENT_SHOULD_KEEP_ALIVE";
  ShapeFlags[(ShapeFlags["COMPONENT_KEPT_ALIVE"] = 1 << 9)] =
    "COMPONENT_KEPT_ALIVE";
  ShapeFlags[
    (ShapeFlags["COMPONENT"] =
      ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT)
  ] = "COMPONENT";
})(ShapeFlags || (ShapeFlags = {}));

export const invokeHooks = (fns) => {
  for (let i = 0; i < fns.length; i++) {
    fns[i]();
  }
};

/**
 * Patch flags are optimization hints generated by the compiler.
 * when a block with dynamicChildren is encountered during diff, the algorithm
 * enters "optimized mode". In this mode, we know that the vdom is produced by
 * a render function generated by the compiler, so the algorithm only needs to
 * handle updates explicitly marked by these patch flags.
 *
 * Patch flags can be combined using the | bitwise operator and can be checked
 * using the & operator, e.g.
 *
 * ```js
 * const flag = TEXT | CLASS
 * if (flag & TEXT) { ... }
 * ```
 *
 * Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the
 * flags are handled during diff.
 */
export let PatchFlags;
(function (PatchFlags) {
  PatchFlags[(PatchFlags["TEXT"] = 1)] = "TEXT";
  PatchFlags[(PatchFlags["CLASS"] = 2)] = "CLASS";
  PatchFlags[(PatchFlags["STYLE"] = 4)] = "STYLE";
  PatchFlags[(PatchFlags["PROPS"] = 8)] = "PROPS";
  PatchFlags[(PatchFlags["FULL_PROPS"] = 16)] = "FULL_PROPS";
  PatchFlags[(PatchFlags["HYDRATE_EVENTS"] = 32)] = "HYDRATE_EVENTS";
  PatchFlags[(PatchFlags["STABLE_FRAGMENT"] = 64)] = "STABLE_FRAGMENT";
  PatchFlags[(PatchFlags["KEYED_FRAGMENT"] = 128)] = "KEYED_FRAGMENT";
  PatchFlags[(PatchFlags["UNKEYED_FRAGMENT"] = 256)] = "UNKEYED_FRAGMENT";
  PatchFlags[(PatchFlags["NEED_PATCH"] = 512)] = "NEED_PATCH";
  PatchFlags[(PatchFlags["DYNAMIC_SLOTS"] = 1024)] = "DYNAMIC_SLOTS";
  PatchFlags[(PatchFlags["DEV_ROOT_FRAGMENT"] = 2048)] = "DEV_ROOT_FRAGMENT";
  PatchFlags[(PatchFlags["HOISTED"] = -1)] = "HOISTED";
  PatchFlags[(PatchFlags["BAIL"] = -2)] = "BAIL";
})(PatchFlags || (PatchFlags = {}));
